package fr.umlv.m2.jee.spij.ldap.actors.dao;

import fr.umlv.m2.jee.spij.ldap.actors.Actor;
import fr.umlv.m2.jee.spij.ldap.actors.IActorDAO;
import fr.umlv.m2.jee.spij.ldap.actors.Mapper.ActorAttributeMapper;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.filter.AndFilter;
import org.springframework.ldap.filter.EqualsFilter;

import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import java.util.ArrayList;
import java.util.List;

/**
 * Provides methods to retrieve Actors into LDAP.
 *
 * @author lounes
 */
public class ActorDAO implements IActorDAO {

    /**
     * The directory context.
     */
    private DirContext ctx;

    /**
     * Constructor.
     *
     * @param myCtx the context.
     */
    public ActorDAO(final DirContext myCtx) {
        this.ctx = myCtx;
    }

    /**
     * Sets the current context.
     *
     * @param newContext the new context.
     */
    public final void setCtx(final DirContext newContext) {
        this.ctx = newContext;
    }

    /**
     * Returns an actor using the login.
     *
     * @param login    the login.
     * @param password the password.
     *
     * @return an actor.
     *
     * @throws NamingException an exception about connexion occured.
     */
    @Override
    public final Actor getUserDetails(final String login, final String password)
            throws NamingException {
        SearchControls controls = new SearchControls();
        controls.setSearchScope(SearchControls.SUBTREE_SCOPE);

        AndFilter andFilter = new AndFilter();
        andFilter.and(new EqualsFilter("objectclass", "person"));
        andFilter.and(new EqualsFilter("uid", login));
        andFilter.and(new EqualsFilter("userPassword", password));
        NamingEnumeration<SearchResult> results =
                ctx.search("", andFilter.encode(), controls);

        AttributesMapper mapper = new ActorAttributeMapper();
        Actor actor = null;
        while (results.hasMore()) {
            SearchResult searchResult = (SearchResult) results.next();
            Attributes attributes = searchResult.getAttributes();
            actor = (Actor) mapper.mapFromAttributes(attributes);
        }
        return actor;
    }

    /**
     * @return a list of Student.
     *
     * @throws NamingException exception.
     */
    @Override
    public final List<Actor> getAllStudent() throws NamingException {
        SearchControls controls = new SearchControls();
        controls.setSearchScope(SearchControls.SUBTREE_SCOPE);

        AndFilter andFilter = new AndFilter();
        andFilter.and(new EqualsFilter("objectclass", "person"));
        andFilter.and(new EqualsFilter("cn", "Student"));
        NamingEnumeration<SearchResult> results =
                ctx.search("", andFilter.encode(), controls);

        AttributesMapper mapper = new ActorAttributeMapper();
        Actor actor = null;
        List<Actor> actorList = new ArrayList<Actor>();
        while (results.hasMore()) {
            SearchResult searchResult = (SearchResult) results.next();
            Attributes attributes = searchResult.getAttributes();
            actor = (Actor) mapper.mapFromAttributes(attributes);
            actorList.add(actor);
        }
        return actorList;

    }

    /**
     * @return a list of Teacher.
     *
     * @throws NamingException exception.
     */
    @Override
    public final List<Actor> getAllTeacher() throws NamingException {
        SearchControls controls = new SearchControls();
        controls.setSearchScope(SearchControls.SUBTREE_SCOPE);

        AndFilter andFilter = new AndFilter();
        andFilter.and(new EqualsFilter("objectclass", "person"));
        andFilter.and(new EqualsFilter("cn", "Teacher"));
        NamingEnumeration<SearchResult> results =
                ctx.search("", andFilter.encode(), controls);

        AttributesMapper mapper = new ActorAttributeMapper();
        Actor actor = null;
        List<Actor> actorList = new ArrayList<Actor>();
        while (results.hasMore()) {
            SearchResult searchResult = (SearchResult) results.next();
            Attributes attributes = searchResult.getAttributes();
            actor = (Actor) mapper.mapFromAttributes(attributes);
            actorList.add(actor);
        }
        return actorList;
    }
}
